# -*- coding: utf-8 -*-
from odoo import models, fields, api
from odoo.exceptions import ValidationError
import csv
import io
import base64
import xlrd
import xlwt


class ItemMaster(models.Model):
    """物料主表"""
    _name = 'item.master'
    _description = '物料主数据'
    _rec_name = 'item_code'
    
    # 主表字段
    item_code = fields.Char(
        string='物料编号',
        required=True,
        help='用于识别物料或产品的唯一编号'
    )
    
    company_id = fields.Many2one(
        'res.company',
        string='公司',
        default=lambda self: self.env.company,
        help='公司标识'
    )
    
    description1 = fields.Char(
        string='描述1',
        help='此物料的第一行描述'
    )
    
    description2 = fields.Char(
        string='描述2',
        help='此物料的第二行描述'
    )
    
    um = fields.Char(
        string='单位',
        required=True,
        default='EA',
        help='此物料的库存计量单位'
    )
    
    # 从表关系
    classification_ids = fields.One2many(
        'item.classification.detail',
        'item_id',
        string='分类明细'
    )
    
    inventory_ids = fields.One2many(
        'item.inventory.detail',
        'item_id',
        string='库存明细'
    )
    
    planning_ids = fields.One2many(
        'item.planning.detail',
        'item_id',
        string='计划明细'
    )
    
    # 唯一性约束
    _sql_constraints = [
        ('item_code_company_unique',
         'UNIQUE(item_code, company_id)',
         '物料编号在同一公司内必须唯一！')
    ]
    
    def name_get(self):
        """显示名称格式"""
        result = []
        for record in self:
            name = record.item_code
            if record.description1:
                name = f"[{record.item_code}] {record.description1}"
            result.append((record.id, name))
        return result
    
    @api.model
    def import_csv_data(self, file_data):
        """导入CSV数据"""
        try:
            # 解码base64数据
            file_content = base64.b64decode(file_data)
            file_content = file_content.decode('utf-8-sig')  # 处理BOM
            
            # 解析CSV
            csv_reader = csv.DictReader(io.StringIO(file_content))
            
            success_count = 0
            error_count = 0
            errors = []
            
            for row_num, row in enumerate(csv_reader, start=2):  # 从第2行开始（跳过标题）
                try:
                    # 准备数据
                    vals = {
                        'item_code': row.get('物料编号', '').strip(),
                        'description1': row.get('描述1', '').strip(),
                        'description2': row.get('描述2', '').strip(),
                        'um': row.get('单位', 'EA').strip(),
                        'company_id': self.env.company.id,
                    }
                    
                    # 验证必填字段
                    if not vals['item_code']:
                        raise ValidationError(f"第{row_num}行：物料编号不能为空")
                    
                    # 检查是否已存在
                    existing = self.search([
                        ('item_code', '=', vals['item_code']),
                        ('company_id', '=', vals['company_id'])
                    ])
                    
                    if existing:
                        # 更新现有记录
                        existing.write(vals)
                        success_count += 1
                    else:
                        # 创建新记录
                        self.create(vals)
                        success_count += 1
                        
                except Exception as e:
                    error_count += 1
                    errors.append(f"第{row_num}行：{str(e)}")
            
            return {
                'success': True,
                'message': f"导入完成！成功：{success_count}条，失败：{error_count}条",
                'errors': errors[:10] if errors else []  # 只显示前10个错误
            }
            
        except Exception as e:
            return {
                'success': False,
                'message': f"导入失败：{str(e)}",
                'errors': []
            }
    
    @api.model
    def import_excel_data(self, file_data):
        """导入Excel数据"""
        try:
            # 解码base64数据
            file_content = base64.b64decode(file_data)
            
            # 读取Excel文件
            workbook = xlrd.open_workbook(file_contents=file_content)
            sheet = workbook.sheet_by_index(0)
            
            # 获取标题行
            headers = []
            for col in range(sheet.ncols):
                headers.append(sheet.cell_value(0, col).strip())
            
            success_count = 0
            error_count = 0
            errors = []
            
            # 处理数据行
            for row_num in range(1, sheet.nrows):
                try:
                    row_data = {}
                    for col, header in enumerate(headers):
                        cell_value = sheet.cell_value(row_num, col)
                        if isinstance(cell_value, str):
                            cell_value = cell_value.strip()
                        row_data[header] = cell_value
                    
                    # 准备数据
                    vals = {
                        'item_code': str(row_data.get('物料编号', '')).strip(),
                        'description1': str(row_data.get('描述1', '')).strip(),
                        'description2': str(row_data.get('描述2', '')).strip(),
                        'um': str(row_data.get('单位', 'EA')).strip(),
                        'company_id': self.env.company.id,
                    }
                    
                    # 验证必填字段
                    if not vals['item_code']:
                        raise ValidationError(f"第{row_num+1}行：物料编号不能为空")
                    
                    # 检查是否已存在
                    existing = self.search([
                        ('item_code', '=', vals['item_code']),
                        ('company_id', '=', vals['company_id'])
                    ])
                    
                    if existing:
                        # 更新现有记录
                        existing.write(vals)
                        success_count += 1
                    else:
                        # 创建新记录
                        self.create(vals)
                        success_count += 1
                        
                except Exception as e:
                    error_count += 1
                    errors.append(f"第{row_num+1}行：{str(e)}")
            
            return {
                'success': True,
                'message': f"导入完成！成功：{success_count}条，失败：{error_count}条",
                'errors': errors[:10] if errors else []  # 只显示前10个错误
            }
            
        except Exception as e:
            return {
                'success': False,
                'message': f"导入失败：{str(e)}",
                'errors': []
            }
    
    def export_template_csv(self):
        """导出CSV模板"""
        template_data = [
            ['物料编号', '描述1', '描述2', '单位'],
            ['PART-001', '测试零件A', '第一个测试零件', 'EA'],
            ['PART-002', '测试零件B', '第二个测试零件', 'PCS'],
        ]
        
        # 创建CSV内容
        output = io.StringIO()
        writer = csv.writer(output)
        for row in template_data:
            writer.writerow(row)
        
        csv_content = output.getvalue()
        output.close()
        
        # 编码为base64
        csv_bytes = csv_content.encode('utf-8-sig')  # 添加BOM以支持中文
        csv_b64 = base64.b64encode(csv_bytes)
        
        return {
            'type': 'ir.actions.act_url',
            'url': f'/web/content?model=ir.attachment&id={self._create_attachment(csv_b64, "物料主数据模板.csv")}&field=datas&download=true',
            'target': 'self',
        }
    
    def export_template_excel(self):
        """导出Excel模板"""
        # 创建工作簿
        workbook = xlwt.Workbook(encoding='utf-8')
        sheet = workbook.add_sheet('物料主数据')
        
        # 设置标题样式
        title_style = xlwt.XFStyle()
        title_font = xlwt.Font()
        title_font.bold = True
        title_style.font = title_font
        
        # 写入标题
        headers = ['物料编号', '描述1', '描述2', '单位']
        for col, header in enumerate(headers):
            sheet.write(0, col, header, title_style)
        
        # 写入示例数据
        sample_data = [
            ['PART-001', '测试零件A', '第一个测试零件', 'EA'],
            ['PART-002', '测试零件B', '第二个测试零件', 'PCS'],
        ]
        
        for row, data in enumerate(sample_data, start=1):
            for col, value in enumerate(data):
                sheet.write(row, col, value)
        
        # 设置列宽
        sheet.col(0).width = 3000  # 物料编号
        sheet.col(1).width = 4000  # 描述1
        sheet.col(2).width = 4000  # 描述2
        sheet.col(3).width = 2000  # 单位
        
        # 保存到内存
        output = io.BytesIO()
        workbook.save(output)
        excel_content = output.getvalue()
        output.close()
        
        # 编码为base64
        excel_b64 = base64.b64encode(excel_content)
        
        return {
            'type': 'ir.actions.act_url',
            'url': f'/web/content?model=ir.attachment&id={self._create_attachment(excel_b64, "物料主数据模板.xls")}&field=datas&download=true',
            'target': 'self',
        }
    
    def _create_attachment(self, content, filename):
        """创建附件并返回ID"""
        attachment = self.env['ir.attachment'].create({
            'name': filename,
            'datas': content,
            'type': 'binary',
            'res_model': 'item.master',
            'res_id': 0,
        })
        return attachment.id


class ItemClassificationDetail(models.Model):
    """物料分类明细表"""
    _name = 'item.classification.detail'
    _description = '物料分类明细'
    
    item_id = fields.Many2one(
        'item.master',
        string='物料',
        required=True,
        ondelete='cascade',
        help='物料标识'
    )
    
    department_id = fields.Many2one(
        'hr.department',
        string='部门',
        help='此物料的默认部门'
    )
    
    drawing = fields.Char(
        string='图纸',
        help='识别此物料图纸的代码'
    )
    
    product_line = fields.Char(
        string='产品线',
        help='此物料所属的产品线'
    )
    
    group = fields.Char(
        string='组',
        help='用于报表目的的产品组'
    )
    
    type = fields.Selection([
        ('raw', '原材料'),
        ('semi', '半成品'),
        ('finished', '成品'),
        ('consumable', '耗材'),
        ('tool', '工具'),
    ], string='物料类型', help='用于分组具有相似特征的物料的代码')
    
    status = fields.Selection([
        ('active', '激活'),
        ('inactive', '未激活'),
        ('obsolete', '已淘汰'),
        ('development', '开发中'),
    ], string='状态', default='active', help='此物料的工程状态')
    
    # 唯一性约束
    _sql_constraints = [
        ('item_department_unique',
         'UNIQUE(item_id, department_id)',
         '同一物料在同一部门内不能重复！')
    ]


class ItemInventoryDetail(models.Model):
    """物料库存明细表"""
    _name = 'item.inventory.detail'
    _description = '物料库存明细'
    
    item_id = fields.Many2one(
        'item.master',
        string='物料',
        required=True,
        ondelete='cascade',
        help='物料标识'
    )
    
    department_id = fields.Many2one(
        'hr.department',
        string='部门',
        help='此物料的默认部门'
    )
    
    location = fields.Char(
        string='库位',
        help='识别此物料库存的默认库位代码'
    )
    
    abc_class = fields.Selection([
        ('A', 'A类'),
        ('B', 'B类'),
        ('C', 'C类'),
    ], string='ABC分类', help='零件的ABC分类（可以计算）')
    
    issue_policy = fields.Boolean(
        string='发料策略',
        help='指定此物料是否打印在领料单上的标志'
    )
    
    # 唯一性约束
    _sql_constraints = [
        ('item_department_unique',
         'UNIQUE(item_id, department_id)',
         '同一物料在同一部门内不能重复！')
    ]


class ItemPlanningDetail(models.Model):
    """物料计划明细表"""
    _name = 'item.planning.detail'
    _description = '物料计划明细'
    
    item_id = fields.Many2one(
        'item.master',
        string='物料',
        required=True,
        ondelete='cascade',
        help='物料标识'
    )
    
    department_id = fields.Many2one(
        'hr.department',
        string='部门',
        help='此物料的默认部门'
    )
    
    pt_phantom = fields.Boolean(
        string='虚拟件',
        help='指定此物料是虚拟件的标志'
    )
    
    purchase_manufacture_type = fields.Selection([
        ('P', '采购'),
        ('M', '生产'),
        ('L', '租赁'),
        ('R', '返修'),
        ('C', '委外'),
        ('F', '固定资产'),
        ('D', '直发'),
    ], string='采购/生产类型', help='此物料的采购/生产代码')
    
    # 唯一性约束
    _sql_constraints = [
        ('item_department_unique',
         'UNIQUE(item_id, department_id)',
         '同一物料在同一部门内不能重复！')
    ]

